home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Graphics / Ghostscript / source / spngp.c < prev    next >
C/C++ Source or Header  |  1997-02-21  |  10KB  |  335 lines

  1. /* Copyright (C) 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* spngp.c */
  20. /* PNG pixel prediction filters */
  21. #include "memory_.h"
  22. #include "strimpl.h"
  23. #include "spngpx.h"
  24.  
  25. /* ------ PNGPredictorEncode/Decode ------ */
  26.  
  27. private_st_PNGP_state();
  28.  
  29. #define ss ((stream_PNGP_state *)st)
  30. #define ss_const ((const stream_PNGP_state *)st_const)
  31.  
  32. /* Define values for case dispatch. */
  33. #define cNone 10
  34. #define cSub 11
  35. #define cUp 12
  36. #define cAverage 13
  37. #define cPaeth 14
  38. #define cOptimum 15
  39. #define cEncode -10
  40. #define cDecode -4
  41. private const byte pngp_case_needs_prev[] = { 0, 0, 1, 1, 1, 1 };
  42.  
  43. /* Set defaults */
  44. private void
  45. s_PNGP_set_defaults(stream_state *st)
  46. {    s_PNGP_set_defaults_inline(ss);
  47. }
  48.  
  49. /* Common (re)initialization. */
  50. private int
  51. s_PNGP_reinit(stream_state *st)
  52. {    if ( ss->prev_row != 0 )
  53.       memset(ss->prev_row + ss->bpp, 0, ss->row_count);
  54.     ss->row_left = 0;
  55.     return 0;
  56. }
  57.  
  58. /* Initialize PNGPredictorEncode filter. */
  59. private int
  60. s_pngp_init(stream_state *st, bool need_prev)
  61. {    int bits_per_pixel = ss->Colors * ss->BitsPerComponent;
  62.     long bits_per_row = (long)bits_per_pixel * ss->Columns;
  63.     byte *prev_row = 0;
  64.  
  65. #if arch_sizeof_long > arch_sizeof_int
  66.     if ( bits_per_row > max_uint * 7L )
  67.       return ERRC;        /****** WRONG ******/
  68. #endif
  69.     ss->row_count = (uint)((bits_per_row + 7) >> 3);
  70.     ss->end_mask = (1 << (-bits_per_row & 7)) - 1;
  71.     ss->bpp = (bits_per_pixel + 7) >> 3;
  72.     if ( need_prev )
  73.       { prev_row = gs_alloc_bytes(st->memory, ss->bpp + ss->row_count,
  74.                       "PNGPredictor prev row");
  75.         if ( prev_row == 0 )
  76.           return ERRC;    /****** WRONG ******/
  77.         memset(prev_row, 0, ss->bpp);
  78.       }
  79.     ss->prev_row = prev_row;
  80.     /* case_index is only preset for encoding */
  81.     return s_PNGP_reinit(st);
  82. }
  83.  
  84. /* Initialize PNGPredictorEncode filter. */
  85. private int
  86. s_PNGPE_init(stream_state *st)
  87. {    return s_pngp_init(st, pngp_case_needs_prev[ss->Predictor - cNone]);
  88. }
  89.  
  90. /* Initialize PNGPredictorDecode filter. */
  91. private int
  92. s_PNGPD_init(stream_state *st)
  93. {    return s_pngp_init(st, true);
  94. }
  95.  
  96. /*
  97.  * Process a partial buffer.  We pass in current and previous pointers
  98.  * to both the current and preceding scan line.  Note that dprev is
  99.  * p - bpp for encoding, q - bpp for decoding; similarly, the 'up' row
  100.  * is the raw data for encoding, the filtered data for decoding.
  101.  * Note also that the case_index cannot be cOptimum.
  102.  */
  103. private int
  104. paeth_predictor(int a, int b, int c)
  105. {
  106. #undef any_abs            /* just in case */
  107. #define any_abs(u) ((u) < 0 ? -(u) : (u))
  108.     int px = a + b - c;
  109.     int pa = any_abs(px - a), pb = any_abs(px - b), pc = any_abs(px - c);
  110.     return (pa <= pb && pa <= pc ? a : pb <= pc ? b : c);
  111. #undef any_abs
  112. }
  113. private void
  114. s_pngp_process(stream_state *st, stream_cursor_write *pw,
  115.   const byte *dprev, stream_cursor_read *pr,
  116.   const byte *upprev, const byte *up, uint count)
  117. {    byte *q = pw->ptr + 1;
  118.     const byte *p = pr->ptr + 1;
  119.  
  120.     pr->ptr += count;
  121.     pw->ptr += count;
  122.     ss->row_left -= count;
  123.     switch ( ss->case_index )
  124.       {
  125.       case cEncode + cNone:
  126.       case cDecode + cNone:
  127.         memcpy(q, p, count);
  128.         break;
  129.       case cEncode + cSub:
  130.         for ( ; count; ++q, ++dprev, ++p, --count )
  131.           *q = (byte)(*p - *dprev);
  132.         break;
  133.       case cDecode + cSub:
  134.         for ( ; count; ++q, ++dprev, ++p, --count )
  135.           *q = (byte)(*p + *dprev);
  136.         break;
  137.       case cEncode + cUp:
  138.         for ( ; count; ++q, ++up, ++p, --count )
  139.           *q = (byte)(*p - *up);
  140.         break;
  141.       case cDecode + cUp:
  142.         for ( ; count; ++q, ++up, ++p, --count )
  143.           *q = (byte)(*p + *up);
  144.         break;
  145.       case cEncode + cAverage:
  146.         for ( ; count; ++q, ++dprev, ++up, ++p, --count )
  147.           *q = (byte)(*p - arith_rshift_1((int)*dprev + (int)*up));
  148.         break;
  149.       case cDecode + cAverage:
  150.         for ( ; count; ++q, ++dprev, ++up, ++p, --count )
  151.           *q = (byte)(*p + arith_rshift_1((int)*dprev + (int)*up));
  152.         break;
  153.       case cEncode + cPaeth:
  154.         for ( ; count; ++q, ++dprev, ++up, ++upprev, ++p, --count )
  155.           *q = (byte)(*p - paeth_predictor(*dprev, *up, *upprev));
  156.         break;
  157.       case cDecode + cPaeth:
  158.         for ( ; count; ++q, ++dprev, ++up, ++upprev, ++p, --count )
  159.           *q = (byte)(*p + paeth_predictor(*dprev, *up, *upprev));
  160.         break;
  161.       }
  162. }
  163.  
  164. /* Calculate the number of bytes for the next processing step, */
  165. /* the min of (input data, output data, remaining row length). */
  166. private uint near
  167. s_pngp_count(const stream_state *st_const, const stream_cursor_read *pr,
  168.   const stream_cursor_write *pw)
  169. {    uint rcount = pr->limit - pr->ptr;
  170.     uint wcount = pw->limit - pw->ptr;
  171.     uint row_left = ss_const->row_left;
  172.  
  173.     if ( rcount < row_left )
  174.       row_left = rcount;
  175.     if ( wcount < row_left )
  176.       row_left = wcount;
  177.     return row_left;
  178. }
  179.  
  180. /*
  181.  * Encode a buffer.  Let N = ss->row_count, P = N - ss->row_left,
  182.  * and B = ss->bpp.  Consider that bytes [-B .. -1] of every row are zero.
  183.  * Then:
  184.  *    prev_row[0 .. P - 1] contain bytes -B .. P - B - 1
  185.  *      of the current input row.
  186.  *    ss->prev[0 .. B - 1] contain bytes P - B .. P - 1
  187.  *      of the current input row.
  188.  *    prev_row[P .. N + B - 1] contain bytes P - B .. N - 1
  189.  *      of the previous input row.
  190.  */
  191. private int
  192. optimum_predictor(const stream_state *st, const stream_cursor_read *pr)
  193. {    return cSub;
  194. }
  195. private int
  196. s_PNGPE_process(stream_state *st, stream_cursor_read *pr,
  197.   stream_cursor_write *pw, bool last)
  198. {    int bpp = ss->bpp;
  199.     int code = 0;
  200.     while ( pr->ptr < pr->limit )
  201.       {    uint count;
  202.         if ( ss->row_left == 0 )
  203.           { /* Beginning of row, write algorithm byte. */
  204.             int predictor;
  205.             if ( pw->ptr >= pw->limit )
  206.               { code = 1;
  207.             break;
  208.               }
  209.             predictor =
  210.               (ss->Predictor == cOptimum ?
  211.                optimum_predictor(st, pr) :
  212.                ss->Predictor);
  213.             *++(pw->ptr) = (byte)predictor - cNone;
  214.             ss->case_index = predictor + cEncode;
  215.             ss->row_left = ss->row_count;
  216.             memset(ss->prev, 0, bpp);
  217.             continue;
  218.           }
  219.         count = s_pngp_count(st, pr, pw);
  220.         if ( count == 0 )
  221.           { /* We know we have input, so output must be full. */
  222.             code = 1;
  223.             break;
  224.           }
  225.         { byte *up = ss->prev_row + bpp + ss->row_count - ss->row_left;
  226.           uint n = min(count, bpp);
  227.  
  228.           /* Process bytes whose predecessors are in prev. */
  229.           s_pngp_process(st, pw, ss->prev, pr, up - bpp, up, n);
  230.           if ( ss->prev_row )
  231.             memcpy(up - bpp, ss->prev, n);
  232.           if ( n < bpp )
  233.             { /* We didn't have enough data to use up all of prev. */
  234.               /* Shift more data into prev and exit. */
  235.               int prev_left = bpp - n;
  236.               memmove(ss->prev, ss->prev + n, prev_left);
  237.               memcpy(ss->prev + prev_left, pr->ptr - (n - 1), n);
  238.               break;
  239.             }
  240.           /* Process bytes whose predecessors are in the input. */
  241.           /* We know we have at least bpp input and output bytes, */
  242.           /* and that n = bpp. */
  243.           count -= bpp;
  244.           s_pngp_process(st, pw, pr->ptr - (bpp - 1), pr,
  245.                  up, up + bpp, count);
  246.           memcpy(ss->prev, pr->ptr - (bpp - 1), bpp);
  247.           if ( ss->prev_row )
  248.             { memcpy(up, pr->ptr - (bpp + count - 1), count);
  249.               if ( ss->row_left == 0 )
  250.             memcpy(up + count, ss->prev, bpp);
  251.             }
  252.         }
  253.       }
  254.     return code;
  255. }
  256.  
  257. /*
  258.  * Decode a buffer.  Let N = ss->row_count, P = N - ss->row_left,
  259.  * and B = ss->bpp.  Consider that bytes [-B .. -1] of every row are zero.
  260.  * Then:
  261.  *    prev_row[0 .. P - 1] contain bytes -B .. P - B - 1
  262.  *      of the current output row.
  263.  *    ss->prev[0 .. B - 1] contain bytes P - B .. P - 1
  264.  *      of the current output row.
  265.  *    prev_row[P .. N + B - 1] contain bytes P - B .. N - 1
  266.  *      of the previous output row.
  267.  */
  268. private int
  269. s_PNGPD_process(stream_state *st, stream_cursor_read *pr,
  270.   stream_cursor_write *pw, bool last)
  271. {    int bpp = ss->bpp;
  272.     int code = 0;
  273.     while ( pr->ptr < pr->limit )
  274.       {    uint count;
  275.         if ( ss->row_left == 0 )
  276.           { /* Beginning of row, read algorithm byte. */
  277.             int predictor = pr->ptr[1];
  278.             if ( predictor >= cOptimum - cNone )
  279.               { code = ERRC;
  280.             break;
  281.               }
  282.             pr->ptr++;
  283.             ss->case_index = predictor + cNone + cDecode;
  284.             ss->row_left = ss->row_count;
  285.             memset(ss->prev, 0, bpp);
  286.             continue;
  287.           }
  288.         count = s_pngp_count(st, pr, pw);
  289.         if ( count == 0 )
  290.           { /* We know we have input, so output must be full. */
  291.             code = 1;
  292.             break;
  293.           }
  294.         { byte *up = ss->prev_row + bpp + ss->row_count - ss->row_left;
  295.           uint n = min(count, bpp);
  296.  
  297.           /* Process bytes whose predecessors are in prev. */
  298.           s_pngp_process(st, pw, ss->prev, pr, up - bpp, up, n);
  299.           if ( ss->prev_row )
  300.             memcpy(up - bpp, ss->prev, n);
  301.           if ( n < bpp )
  302.             { /* We didn't have enough data to use up all of prev. */
  303.               /* Shift more data into prev and exit. */
  304.               int prev_left = bpp - n;
  305.               memmove(ss->prev, ss->prev + n, prev_left);
  306.               memcpy(ss->prev + prev_left, pw->ptr - (n - 1), n);
  307.               break;
  308.             }
  309.           /* Process bytes whose predecessors are in the output. */
  310.           /* We know we have at least bpp input and output bytes, */
  311.           /* and that n = bpp. */
  312.           count -= bpp;
  313.           s_pngp_process(st, pw, pw->ptr - (bpp - 1), pr,
  314.                  up, up + bpp, count);
  315.           memcpy(ss->prev, pw->ptr - (bpp - 1), bpp);
  316.           if ( ss->prev_row )
  317.             { memcpy(up, pw->ptr - (bpp + count - 1), count);
  318.               if ( ss->row_left == 0 )
  319.             memcpy(up + count, ss->prev, bpp);
  320.             }
  321.         }
  322.       }
  323.     return code;
  324. }
  325.  
  326. /* Stream templates */
  327. const stream_template s_PNGPE_template =
  328. {    &st_PNGP_state, s_PNGPE_init, s_PNGPE_process, 1, 1, 0/*NULL*/,
  329.     s_PNGP_set_defaults, s_PNGP_reinit
  330. };
  331. const stream_template s_PNGPD_template =
  332. {    &st_PNGP_state, s_PNGPD_init, s_PNGPD_process, 1, 1, 0/*NULL*/,
  333.     s_PNGP_set_defaults, s_PNGP_reinit
  334. };
  335.